﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Threading;
using mat2tab_fun.functionPlots;

namespace mat2tab_fun
{
    /// <summary>
    /// Interaction logic for FunctionsPage2.xaml
    /// </summary>
    public partial class FunctionsPage2 : Page, ISwitchable
    {
        FunctionPlot functionPlot;
        string functionName;
        private bool testMonotonicznosci = false;

        public FunctionsPage2()
        {
            InitializeComponent();
        }

        private void backButton_Click(object sender, RoutedEventArgs e)
        {
            Switcher.Switch(new Menu());
        }

        public void UtilizeState(object state)
        {
            throw new NotImplementedException();
        }

        // narysowanie siatki wykresu ( size - odstep miedzy liniami )
        protected void DrawPlotLines(int size)
        {
            plotGrid.Children.Clear();
            double thickness = 1;
            if (size < 10)
                thickness = 0.3;
            else if (size < 18)
                thickness = 0.4;
            else if (size < 25)
                thickness = 0.5;
            /* Rysowanie linii pionowych */
            for (int i = (int)plotGrid.ActualWidth / 2, j = (int)plotGrid.ActualWidth / 2; 
                i >= 0 && j <= plotGrid.ActualWidth ; 
                i -= size, j+= size )
            {
                // linie od srodka na lewo
                Line y1 = new Line();
                y1.StrokeThickness = thickness;
                y1.Stroke = Brushes.Black;
                y1.X1 = y1.X2 = i;
                y1.Y1 = 0;
                y1.Y2 = plotGrid.ActualHeight;
                plotGrid.Children.Add(y1);

                // linie od srodka na prawo
                Line y2 = new Line();
                y2.StrokeThickness = thickness;
                y2.Stroke = Brushes.Black;
                y2.X1 = y2.X2 = j;
                y2.Y1 = 0;
                y2.Y2 = plotGrid.ActualWidth;
                plotGrid.Children.Add(y2);
            }

            /* Rysowanie linii poziomych */
            for (int i = (int)plotGrid.ActualHeight / 2, j = (int)plotGrid.ActualHeight / 2;
                i >= 0 && j <= plotGrid.ActualHeight;
                i -= size, j += size)
            {
                // linie od srodka  do gory
                Line x1 = new Line();
                x1.StrokeThickness = thickness;
                x1.Stroke = Brushes.Black;
                x1.X1 = 0;
                x1.X2 = plotGrid.ActualWidth;
                x1.Y1 = x1.Y2 = i;
                plotGrid.Children.Add(x1);

                // linie od srodka na dol
                Line x2 = new Line();
                x2.StrokeThickness = thickness;
                x2.Stroke = Brushes.Black;
                x2.X1 = 0;
                x2.X2 = plotGrid.ActualWidth;
                x2.Y1 = x2.Y2 = j;
                plotGrid.Children.Add(x2);
            }

            /* Rysowanie osi zerowych X i Y wykresu */
            Line x = new Line();
            x.StrokeThickness = 3;
            x.Stroke = Brushes.Black;
            x.X1 = 0;
            x.X2 = plotGrid.ActualWidth;
            x.Y1 = x.Y2 = plotGrid.ActualHeight / 2;
            plotGrid.Children.Add(x);

            Line y = new Line();
            y.StrokeThickness = 3;
            y.Stroke = Brushes.Black;
            y.X1 = y.X2 = plotGrid.ActualWidth / 2;
            y.Y1 = 0; y.Y2 = plotGrid.ActualHeight;
            plotGrid.Children.Add(y);
        }

        private void rysuj_Click(object sender, RoutedEventArgs e)
        {
            draw();
        }

        private void HandleCheck(object sender, RoutedEventArgs e)
        {
            testMonotonicznosci = true;
            draw();
        }

        private void HandleUnchecked(object sender, RoutedEventArgs e)
        {
            testMonotonicznosci = false;
            draw();
        }

        private void draw()
        {
            try
            {
                plotGrid.Children.Clear();
                DrawPlotLines((int)sizeSlider.Value);


                if (functionList.SelectedIndex == 0)
                    functionPlot = new PolynomialFunctionPlot(testMonotonicznosci, plotGrid, (int)sizeSlider.Value, (int)fSlider1.Value, (int)fSlider0.Value);
                else if (functionList.SelectedIndex == 1)
                    functionPlot = new PolynomialFunctionPlot(testMonotonicznosci, plotGrid, (int)sizeSlider.Value, (int)fSlider2.Value, (int)fSlider1.Value, (int)fSlider0.Value);
                else if (functionList.SelectedIndex == 2)
                    functionPlot = new PolynomialFunctionPlot(testMonotonicznosci, plotGrid, (int)sizeSlider.Value, (int)fSlider3.Value, (int)fSlider2.Value, (int)fSlider1.Value, (int)fSlider0.Value);
                else if (functionList.SelectedIndex == 3)
                    functionPlot = new PolynomialFunctionPlot(testMonotonicznosci, plotGrid, (int)sizeSlider.Value, (int)fSlider4.Value, (int)fSlider3.Value, (int)fSlider2.Value, (int)fSlider1.Value, (int)fSlider0.Value);
                else if (functionList.SelectedIndex == 4)
                    functionPlot = new PolynomialFunctionPlot(testMonotonicznosci, plotGrid, (int)sizeSlider.Value, (int)fSlider5.Value, (int)fSlider4.Value, (int)fSlider3.Value, (int)fSlider2.Value, (int)fSlider1.Value, (int)fSlider0.Value);
                else if (functionList.SelectedIndex == 5)
                    functionPlot = new TrigonometricFunctionPlot(testMonotonicznosci, plotGrid, (int)sizeSlider.Value, "SIN", (int)tfSliderA.Value, (int)tfSliderB.Value, (int)tfSliderC.Value);
                else if (functionList.SelectedIndex == 6)
                    functionPlot = new TrigonometricFunctionPlot(testMonotonicznosci, plotGrid, (int)sizeSlider.Value, "COS", (int)tfSliderA.Value, (int)tfSliderB.Value, (int)tfSliderC.Value);
                else if (functionList.SelectedIndex == 7)
                    functionPlot = new TrigonometricFunctionPlot(testMonotonicznosci, plotGrid, (int)sizeSlider.Value, "TAN", (int)tfSliderA.Value, (int)tfSliderB.Value, (int)tfSliderC.Value);
                else if (functionList.SelectedIndex == 8)
                    functionPlot = new TrigonometricFunctionPlot(testMonotonicznosci, plotGrid, (int)sizeSlider.Value, "CTAN", (int)tfSliderA.Value, (int)tfSliderB.Value, (int)tfSliderC.Value);
                else if (functionList.SelectedIndex == 9)
                    functionPlot = new ExponentialFunctionPlot(testMonotonicznosci, plotGrid, (int)sizeSlider.Value, (int)tfSliderA.Value, tfSliderB.Value, (int)tfSliderC.Value);
                else if (functionList.SelectedIndex == 10)
                    functionPlot = new LogarythmicFunctionPlot(testMonotonicznosci, plotGrid, (int)sizeSlider.Value, (int)tfSliderA.Value, tfSliderB.Value, (int)tfSliderC.Value);
            }
            catch (Exception)
            { 
            
            }
        }
        private void Page_Loaded(object sender, RoutedEventArgs e)
        {
            DrawPlotLines(50);
        }

        // zmiana jednostki wykresu
        private void sizeSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            plotGrid.Children.Clear();
            DrawPlotLines((int)e.NewValue);
            try
            {
                rysuj_Click(sender, e);
            }
            catch (Exception)
            {
            }
        }

        // Udostepnianie sliderow w zaleznosci od wybranej funcji
        private void functionList_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            try
            {
                switch (functionList.SelectedIndex)
                {
                    case 0:
                        enablefSliders();
                        fSlider0.IsEnabled = true;
                        fSlider1.IsEnabled = true;
                        fSlider2.IsEnabled = false;
                        fSlider3.IsEnabled = false;
                        fSlider4.IsEnabled = false;
                        fSlider5.IsEnabled = false;
                        changefSlidersValue();
                        break;
                    case 1:
                        enablefSliders();
                        fSlider0.IsEnabled = true;
                        fSlider1.IsEnabled = true;
                        fSlider2.IsEnabled = true;
                        fSlider3.IsEnabled = false;
                        fSlider4.IsEnabled = false;
                        fSlider5.IsEnabled = false;
                        changefSlidersValue();
                        break;
                    case 2:
                        enablefSliders();
                        fSlider0.IsEnabled = true;
                        fSlider1.IsEnabled = true;
                        fSlider2.IsEnabled = true;
                        fSlider3.IsEnabled = true;
                        fSlider4.IsEnabled = false;
                        fSlider5.IsEnabled = false;
                        changefSlidersValue();
                        break;
                    case 3:
                        enablefSliders();
                        fSlider0.IsEnabled = true;
                        fSlider1.IsEnabled = true;
                        fSlider2.IsEnabled = true;
                        fSlider3.IsEnabled = true;
                        fSlider4.IsEnabled = true;
                        fSlider5.IsEnabled = false;
                        changefSlidersValue();
                        break;
                    case 4:
                        enablefSliders();
                        fSlider0.IsEnabled = true;
                        fSlider1.IsEnabled = true;
                        fSlider2.IsEnabled = true;
                        fSlider3.IsEnabled = true;
                        fSlider4.IsEnabled = true;
                        fSlider5.IsEnabled = true;
                        changefSlidersValue();
                        break;
                    case 5:
                        functionName = "sin";
                        changeTfSliderValue();
                        enableTfSliders();
                        break;
                    case 6:
                        functionName = "cos";
                        changeTfSliderValue();
                        enableTfSliders();
                        break;
                    case 7:
                        functionName = "tg";
                        changeTfSliderValue();
                        enableTfSliders();
                        break;
                    case 8:
                        functionName = "ctg";
                        changeTfSliderValue();
                        enableTfSliders();
                        break;
                    case 9:
                        functionName = "exp";
                        changeTfSliderValue();
                        enableTfSliders();
                        break;
                    case 10:
                        functionName = "log";
                        enableTfSliders();
                        changeTfSliderValue();
                        break;
                }
                resetSliders();
                draw();
            }
            catch (Exception)
            {

            }
        }

        void resetSliders()
        {
            fSlider0.Value = 1;
            fSlider1.Value = 1;
            fSlider2.Value = 1;
            fSlider3.Value = 1;
            fSlider4.Value = 1;
            fSlider5.Value = 1;
            tfSliderA.Value = 1;
            tfSliderB.Value = 1;
            tfSliderC.Value = 1;
            changefSlidersValue();
            changeTfSliderValue();
        }

        // wylaczenie widzialnosci sliderow i labeli od funkcji wielomianowych
        private void disablefSliders()
        {
            pfSlidersGrid.Visibility = Visibility.Hidden;
        }

        // wlaczenie widzialnosci sliderow i labeli od funkcji wielomianowych
        private void enablefSliders()
        {
            disableTfSliders();

            pfSlidersGrid.Visibility = Visibility.Visible;
        }

        // wlaczenie widzialnosci sliderow i labeli od funkcji trygonometrycznych
        private void enableTfSliders()
        {
            disablefSliders();
            tfSlidersGrid.Visibility = Visibility.Visible;
            if (functionName.Equals("log"))
            {
                tfSliderB.Minimum = 0;
                tfSliderC.Minimum = 2;
            }
            else if (functionName.Equals("exp"))
                tfSliderB.Minimum = 0;
            else
            {
                tfSliderB.Minimum = -20;
                tfSliderC.Minimum = -20;
            }
        }

        // wylaczenie widzialnosci sliderow i labeli od funkcji trygonometrycznych
        private void disableTfSliders()
        {
            tfSlidersGrid.Visibility = Visibility.Hidden;
        }

        #region Zmiana wartosci suwakow
        private void fSlider5_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            changefSlidersValue();
        }

        private void fSlider4_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            changefSlidersValue();
        }

        private void fSlider3_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            changefSlidersValue();
        }

        private void fSlider2_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            changefSlidersValue();
        }

        private void fSlider1_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            changefSlidersValue();
        }

        private void fSlider0_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            changefSlidersValue();
        }

        private void tfSliderA_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            changeTfSliderValue();
        }

        private void tfSliderB_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            changeTfSliderValue();
        }

        private void tfSliderC_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            changeTfSliderValue();
        }  
        #endregion

        private void changefSlidersValue()
        {
            try
            {
                int x5 = (int)fSlider5.Value;
                int x4 = (int)fSlider4.Value;
                int x3 = (int)fSlider3.Value;
                int x2 = (int)fSlider2.Value;
                int x1 = (int)fSlider1.Value;
                int x0 = (int)fSlider0.Value;

                if (fSlider5.IsEnabled)
                {
                    functionLabel.Content = "y = " + (x5 < 0 ? "-" : "") +
                        (x5 == 1 || x5 == 0 || x5 == -1 ? "" : (Math.Abs(x5)).ToString()) + (x5 == 0 ? "" : "x^5") + (x5 == 0 ? "" :(x4 < 0 ? " - " : (x4 == 0 ? "" : " + "))) +
                        (x4 == 1 || x4 == 0 || x4 == -1 ? "" : (Math.Abs(x4)).ToString()) + (x4 == 0 ? "" : "x^4") + (x4 == 0 && x5 == 0 ? "" :(x3 < 0 ? " - " : (x3 == 0 ? "" : " + "))) +
                        (x3 == 1 || x3 == 0 || x3 == -1 ? "" : (Math.Abs(x3)).ToString()) + (x3 == 0 ? "" : "x^3") + (x3 == 0 && x4 == 0 && x5 == 0 ? "" : (x2 < 0 ? " - " : (x2 == 0 ? "" : " + "))) +
                        (x2 == 1 || x2 == 0 || x2 == -1 ? "" : (Math.Abs(x2)).ToString()) + (x2 == 0 ? "" : "x^2") + (x2 == 0 && x3 == 0 && x4 == 0 && x5 == 0 ? "" :(x1 < 0 ? " - " : (x1 == 0 ? "" : " + "))) +
                        (x1 == 1 || x1 == 0 || x1 == -1 ? "" : (Math.Abs(x1)).ToString()) + (x1 == 0 ? "" : "x")   + (x1 == 0 && x2 == 0 && x3 == 0 && x4 == 0 && x5 == 0? "" :(x0 < 0 ? " - " : (x0 == 0 ? "" : " + "))) +
                        (x0 == 0 || x0 == 0 || x0 == -1 ? "" : (Math.Abs(x0)).ToString());
                }
                else if (fSlider4.IsEnabled)
                {
                    functionLabel.Content = "y = " + (x4 < 0 ? "-" : "") +
                       (x4 == 1 || x4 == 0 || x4 == -1 ? "" : (Math.Abs(x4)).ToString()) + (x4 == 0 ? "" : "x^4") + (x4 == 0 && x5 == 0 ? "" : (x3 < 0 ? " - " : (x3 == 0 ? "" : " + "))) +
                       (x3 == 1 || x3 == 0 || x3 == -1 ? "" : (Math.Abs(x3)).ToString()) + (x3 == 0 ? "" : "x^3") + (x3 == 0 && x4 == 0 && x5 == 0 ? "" : (x2 < 0 ? " - " : (x2 == 0 ? "" : " + "))) +
                       (x2 == 1 || x2 == 0 || x2 == -1 ? "" : (Math.Abs(x2)).ToString()) + (x2 == 0 ? "" : "x^2") + (x2 == 0 && x3 == 0 && x4 == 0 && x5 == 0 ? "" : (x1 < 0 ? " - " : (x1 == 0 ? "" : " + "))) +
                       (x1 == 1 || x1 == 0 || x1 == -1 ? "" : (Math.Abs(x1)).ToString()) + (x1 == 0 ? "" : "x") + (x1 == 0 && x2 == 0 && x3 == 0 && x4 == 0 && x5 == 0 ? "" : (x0 < 0 ? " - " : (x0 == 0 ? "" : " + "))) +
                       (x0 == 0 || x0 == 0 || x0 == -1 ? "" : (Math.Abs(x0)).ToString());
                }
                else if (fSlider3.IsEnabled)
                {
                    functionLabel.Content = "y = " + (x3 < 0 ? "-" : "") +
                       (x3 == 1 || x3 == 0 || x3 == -1 ? "" : (Math.Abs(x3)).ToString()) + (x3 == 0 ? "" : "x^3") + (x3 == 0 && x4 == 0 && x5 == 0 ? "" : (x2 < 0 ? " - " : (x2 == 0 ? "" : " + "))) +
                       (x2 == 1 || x2 == 0 || x2 == -1 ? "" : (Math.Abs(x2)).ToString()) + (x2 == 0 ? "" : "x^2") + (x2 == 0 && x3 == 0 && x4 == 0 && x5 == 0 ? "" : (x1 < 0 ? " - " : (x1 == 0 ? "" : " + "))) +
                       (x1 == 1 || x1 == 0 || x1 == -1 ? "" : (Math.Abs(x1)).ToString()) + (x1 == 0 ? "" : "x") + (x1 == 0 && x2 == 0 && x3 == 0 && x4 == 0 && x5 == 0 ? "" : (x0 < 0 ? " - " : (x0 == 0 ? "" : " + "))) +
                       (x0 == 0 || x0 == 0 || x0 == -1 ? "" : (Math.Abs(x0)).ToString());
                }
                else if (fSlider2.IsEnabled)
                {
                    functionLabel.Content = "y = " + (x2 < 0 ? "-" : "") +
                       (x2 == 1 || x2 == 0 || x2 == -1 ? "" : (Math.Abs(x2)).ToString()) + (x2 == 0 ? "" : "x^2") + (x2 == 0 && x3 == 0 && x4 == 0 && x5 == 0 ? "" : (x1 < 0 ? " - " : (x1 == 0 ? "" : " + "))) +
                       (x1 == 1 || x1 == 0 || x1 == -1 ? "" : (Math.Abs(x1)).ToString()) + (x1 == 0 ? "" : "x") + (x1 == 0 && x2 == 0 && x3 == 0 && x4 == 0 && x5 == 0 ? "" : (x0 < 0 ? " - " : (x0 == 0 ? "" : " + "))) +
                       (x0 == 0 || x0 == 0 || x0 == -1 ? "" : (Math.Abs(x0)).ToString());
                }
                else
                {
                    functionLabel.Content = "y = " + (x1 < 0 ? "-" : "") +
                       (x1 == 1 || x1 == 0 || x1 == -1 ? "" : (Math.Abs(x1)).ToString()) + (x1 == 0 ? "" : "x") + (x1 == 0 && x2 == 0 && x3 == 0 && x4 == 0 && x5 == 0 ? "" : (x0 < 0 ? " - " : (x0 == 0 ? "" : " + "))) +
                       (x0 == 0 || x0 == 0 || x0 == -1 ? "" : (Math.Abs(x0)).ToString());
                }
                draw();
            }
            catch (Exception)
            {     
            }
        }

        private void changeTfSliderValue()
        {
            try
            {
                int a = (int)tfSliderA.Value;
                int b = (int)tfSliderB.Value;
                string bl = string.Format("{0:0.00}", tfSliderB.Value);
                int c = (int)tfSliderC.Value;

                if(functionName.Equals("log"))
                {
                        functionLabel.Content = "y = " + (a < 0 ? "-" : "") +
                                (a == 1 || a == 0 || a == -1 ? "" : (Math.Abs(a)).ToString()) + (a == 0 ? "" : functionName) +
                                bl +  "( " + (c == 1  ? "" : (Math.Abs(c)).ToString()) + "x )";
                }
                else if (functionName.Equals("exp"))
                {
                        functionLabel.Content = "y = " + (a < 0 ? "-" : "") +
                            (a == 1 || a == 0 ? "" : (Math.Abs(a)).ToString()) + (a == 0 || a == 1 ? "" :  "*") +
                                (a == 0 || tfSliderB.Value == 0 ? "" : bl + "^x ") +
                                (c > 0 ? "+" : (c == 0 ? "" : "-")) + (c == 0 ? "" : (Math.Abs(c)).ToString());
                }
                else
                {
                    if (a == 0)
                        functionLabel.Content = "y = 0";
                    else if (b == 0)
                        functionLabel.Content = "y = " + a.ToString();
                    else
                        functionLabel.Content = "y = " + (a < 0 ? "-" : "") +
                                (a == 1 || a == 0 || a == -1 ? "" : (Math.Abs(a)).ToString()) + (a == 0 ? "" : functionName) +
                                (b == 1 ? "" : "^" + b.ToString()) + " ( " + (c < 0 ? "-" : "") +
                                (c == 1 || c == -1 ? "" : (Math.Abs(c)).ToString()) + "x )";
                }
                draw();
            }
            catch (Exception)
            {

            }
        }

        private void wyczysc_Click(object sender, RoutedEventArgs e)
        {
            DrawPlotLines((int)sizeSlider.Value);
        }             
    }
}
